#pragma once

#include <mysql/jdbc.h>
#include <cppconn/driver.h>
#include <cppconn/connection.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
#include <cppconn/resultset.h>
#include <cppconn/exception.h>
#include <string>
#include <vector>
#include <memory>
#include <iostream>

using namespace std;
using namespace sql;

// 小说状态枚举
enum class NovelStatus {
    ONGOING,
    COMPLETED,
    DROPPED
};

// Novel 结构体定义
struct Novel {
    int _id;             // 小说编号
    std::string _name;    // 小说名称
    int _author_id;       // 作者编号
    NovelStatus _status;   // 小说状态
    int _count_page;      // 小说页数
    std::string _type;    // 所属栏目/小说类别
    int _count_chapter;   // 小说章节
    int _count_ticket;    // 投票数量

    Novel() {}

    Novel(int id,const std::string& name, int authorId, NovelStatus status, int countPage, const std::string& type, int countChapter, int countTicket)
    : _id(id), _name(name), _author_id(authorId), _status(status), _count_page(countPage), _type(type), _count_chapter(countChapter), _count_ticket(countTicket) {}
     // 状态枚举转字符串
    std::string statusToString() const {
        switch (_status) {
            case NovelStatus::ONGOING: return "ongoing";
            case NovelStatus::COMPLETED: return "completed";
            case NovelStatus::DROPPED: return "dropped";
            default: return "ongoing";
        }
    }

    // 字符串转状态枚举
    static NovelStatus stringToStatus(const std::string& statusStr) {
        if (statusStr == "ongoing") return NovelStatus::ONGOING;
        if (statusStr == "completed") return NovelStatus::COMPLETED;
        if (statusStr == "dropped") return NovelStatus::DROPPED;
        return NovelStatus::ONGOING;
    }
};

class NovelMapper {
private:
    sql::mysql::MySQL_Driver* driver;
    std::unique_ptr<sql::Connection> conn;

public:
    NovelMapper(const std::string& host, const std::string& user, 
               const std::string& password, const std::string& database)
    {
        driver = sql::mysql::get_mysql_driver_instance();
        conn.reset(driver->connect(host, user, password));
        conn->setSchema(database);
    }

    // 插入新小说
    int insertNovel(const Novel& novel) {
        std::string sql = "INSERT INTO novels (_name, _author_id, _statu, _count_page, "
                          "_type, _count_chapter, _count_ticket) "
                          "VALUES (?, ?, ?, ?, ?, ?, ?)";
        
        std::unique_ptr<sql::PreparedStatement> pstmt(conn->prepareStatement(sql));
        pstmt->setString(1, novel._name);
        pstmt->setInt(2, novel._author_id);
        pstmt->setString(3, novel.statusToString());
        pstmt->setInt(4, novel._count_page);
        pstmt->setString(5, novel._type);
        pstmt->setInt(6, novel._count_chapter);
        pstmt->setInt(7, novel._count_ticket);
        
        pstmt->executeUpdate();
        
        // 获取自增ID
        std::unique_ptr<sql::Statement> stmt(conn->createStatement());
        std::unique_ptr<sql::ResultSet> res(stmt->executeQuery("SELECT LAST_INSERT_ID()"));
        if (res->next()) {
            return res->getInt(1);
        }
        return -1; // 插入失败
    }

    // 删除小说
    bool deleteNovel(int novelId) {
        std::string sql = "DELETE FROM novels WHERE _id = ?";
        std::unique_ptr<sql::PreparedStatement> pstmt(conn->prepareStatement(sql));
        pstmt->setInt(1, novelId);
        
        return pstmt->executeUpdate() > 0;
    }

    // 更新小说信息
    bool updateNovel(const Novel& novel) {
        std::string sql = "UPDATE novels SET "
                          "_name = ?, _author_id = ?, _statu = ?, _count_page = ?, "
                          "_type = ?, _count_chapter = ?, _count_ticket = ? "
                          "WHERE _id = ?";
        
        std::unique_ptr<sql::PreparedStatement> pstmt(conn->prepareStatement(sql));
        pstmt->setString(1, novel._name);
        pstmt->setInt(2, novel._author_id);
        pstmt->setString(3, novel.statusToString());
        pstmt->setInt(4, novel._count_page);
        pstmt->setString(5, novel._type);
        pstmt->setInt(6, novel._count_chapter);
        pstmt->setInt(7, novel._count_ticket);
        pstmt->setInt(8, novel._id);
        
        return pstmt->executeUpdate() > 0;
    }

    // 根据ID查询小说
    Novel getNovelById(int novelId) {
        std::string sql = "SELECT _id, _name, _author_id, _statu, _count_page, "
                          "_type, _count_chapter, _count_ticket "
                          "FROM novels WHERE _id = ?";
        
        std::unique_ptr<sql::PreparedStatement> pstmt(conn->prepareStatement(sql));
        pstmt->setInt(1, novelId);
        std::unique_ptr<sql::ResultSet> res(pstmt->executeQuery());
        
        Novel novel;
        if (res->next()) {
            novel._id = res->getInt("_id");
            novel._name = res->getString("_name");
            novel._author_id = res->getInt("_author_id");
            novel._status = Novel::stringToStatus(res->getString("_statu"));
            novel._count_page = res->getInt("_count_page");
            novel._type = res->getString("_type");
            novel._count_chapter = res->getInt("_count_chapter");
            novel._count_ticket = res->getInt("_count_ticket");
        }
        return novel;
    }

    // 查询所有小说
    std::vector<Novel> getAllNovels() {
        std::string sql = "SELECT _id, _name, _author_id, _statu, _count_page, "
                          "_type, _count_chapter, _count_ticket FROM novels";
        
        std::unique_ptr<sql::Statement> stmt(conn->createStatement());
        std::unique_ptr<sql::ResultSet> res(stmt->executeQuery(sql));
        
        std::vector<Novel> novels;
        while (res->next()) {
            Novel novel;
            novel._id = res->getInt("_id");
            novel._name = res->getString("_name");
            novel._author_id = res->getInt("_author_id");
            novel._status = Novel::stringToStatus(res->getString("_statu"));
            novel._count_page = res->getInt("_count_page");
            novel._type = res->getString("_type");
            novel._count_chapter = res->getInt("_count_chapter");
            novel._count_ticket = res->getInt("_count_ticket");
            novels.push_back(novel);
        }
        return novels;
    }

    // 根据作者ID查询
    std::vector<Novel> getNovelsByAuthor(int authorId) {
        std::string sql = "SELECT _id, _name, _author_id, _statu, _count_page, "
                          "_type, _count_chapter, _count_ticket "
                          "FROM novels WHERE _author_id = ?";
        
        std::unique_ptr<sql::PreparedStatement> pstmt(conn->prepareStatement(sql));
        pstmt->setInt(1, authorId);
        std::unique_ptr<sql::ResultSet> res(pstmt->executeQuery());
        
        std::vector<Novel> novels;
        while (res->next()) {
            Novel novel;
            novel._id = res->getInt("_id");
            novel._name = res->getString("_name");
            novel._author_id = res->getInt("_author_id");
            novel._status = Novel::stringToStatus(res->getString("_statu"));
            novel._count_page = res->getInt("_count_page");
            novel._type = res->getString("_type");
            novel._count_chapter = res->getInt("_count_chapter");
            novel._count_ticket = res->getInt("_count_ticket");
            novels.push_back(novel);
        }
        return novels;
    }

    // 根据状态查询
    std::vector<Novel> getNovelsByStatus(NovelStatus status) {
        std::string statusStr = [status]{
            switch(status) {
                case NovelStatus::ONGOING: return "ongoing";
                case NovelStatus::COMPLETED: return "completed";
                case NovelStatus::DROPPED: return "dropped";
                default: return "ongoing";
            }
        }();

        std::string sql = "SELECT _id, _name, _author_id, _statu, _count_page, "
                          "_type, _count_chapter, _count_ticket "
                          "FROM novels WHERE _statu = ?";
        
        std::unique_ptr<sql::PreparedStatement> pstmt(conn->prepareStatement(sql));
        pstmt->setString(1, statusStr);
        std::unique_ptr<sql::ResultSet> res(pstmt->executeQuery());
        
        std::vector<Novel> novels;
        while (res->next()) {
            Novel novel;
            novel._id = res->getInt("_id");
            novel._name = res->getString("_name");
            novel._author_id = res->getInt("_author_id");
            novel._status = Novel::stringToStatus(res->getString("_statu"));
            novel._count_page = res->getInt("_count_page");
            novel._type = res->getString("_type");
            novel._count_chapter = res->getInt("_count_chapter");
            novel._count_ticket = res->getInt("_count_ticket");
            novels.push_back(novel);
        }
        return novels;
    }
};
